﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Happy.Examples.ManufactureManagement.Domain.QualityTests;
using Happy.Examples.ManufactureManagement.Domain.SmallCuts;

namespace Happy.Examples.ManufactureManagement.Domain.Services
{
    public sealed class QualityTestManager
    {
        private readonly ISmallCutRepository _smallCutRepository;

        public QualityTestManager(ISmallCutRepository smallCutRepository)
        {
            _smallCutRepository = smallCutRepository;
        }

        public void Save(
            QualityTest qualityTest,
            IEnumerable<QualityTestItem> addedItems,
            IEnumerable<QualityTestItem> deletedItems)
        {
            qualityTest.AddItems(addedItems);
            qualityTest.DeleteItems(deletedItems);

            qualityTest.Save();

            this.AcquireLocks(qualityTest, addedItems);
            this.ReleaseLocks(qualityTest, deletedItems);
        }

        public void Submit(
            QualityTest qualityTest,
            IEnumerable<QualityTestItem> addedItems,
            IEnumerable<QualityTestItem> deletedItems)
        {
            qualityTest.AddItems(addedItems);
            qualityTest.DeleteItems(deletedItems);

            qualityTest.Submit();

            this.AcquireLocks(qualityTest, addedItems);
            this.ReleaseLocks(qualityTest, deletedItems);
        }

        public void Verify(QualityTest qualityTest)
        {
            qualityTest.Verify();

            foreach (var item in qualityTest.Items)
            {
                var smallCut = _smallCutRepository.Load(item.SmallCutId);
                smallCut.ReleaseLock(CreateLockInfo(qualityTest));
            }
        }

        private void AcquireLocks(QualityTest qualityTest, IEnumerable<QualityTestItem> addedItems)
        {
            foreach (var item in addedItems)
            {
                var smallCut = _smallCutRepository.Load(item.SmallCutId);
                smallCut.AcquireLock(CreateLockInfo(qualityTest));
            }
        }

        private void ReleaseLocks(QualityTest qualityTest, IEnumerable<QualityTestItem> deletedItems)
        {
            foreach (var item in deletedItems)
            {
                var smallCut = _smallCutRepository.Load(item.SmallCutId);
                smallCut.ReleaseLock(CreateLockInfo(qualityTest));
            }
        }

        private static LockInfo CreateLockInfo(QualityTest qualityTest)
        {
            return new LockInfo(LockType.LockByQualityTest, qualityTest.Id);
        }
    }
}
